package model

import (
	"fmt"
	jsoniter "github.com/json-iterator/go"
	"gowork/autoPurchase/pool"
	"gowork/autoPurchase/utils"
	"sync"
	"time"
)

type RawMaterial struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	RelatedRawMaterialsId int64
	Associated int // 1 关联  2 不关联
	AutoPurchase int  // 1 自动采购  2 非自动采购
	Stock int64
	AutoPurchaseRawMaterialSupplierList []*AutoPurchaseRawMaterialSupplier `xorm:"-"`
	//AutomaticPurchaseAuditStatus int  // 1 新提交  2 审核通过  3审核不通过
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Supplier struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	CreatedAt time.Time
	UpdatedAt time.Time
}

type AutoPurchaseRawMaterialSupplier struct {
	Id int64 `xorm:"pk autoincr"`
	RawMaterialId int64
	RawMaterialName string
	SupplierId int64
	SupplierName string
	PurchasePriority int
	MaxQuantification int64
	MinQuantification int64
	MinNumberPackages int
	LeadTime int
	PrepaymentList []*Prepayment `xorm:"-"`
	PurchaseUnitPriceList []*PurchaseUnitPrice `xorm:"-"`
	AnyGifts int // 1 有赠品  2 不赠送
	TemporaryCoordinationGifts int64
	GiftProportionList []*GiftProportion `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Prepayment struct {
	Id int64 `xorm:"pk autoincr"`
	Number int
	AutoPurchaseRawMaterialSupplierId int64
	AdvanceRatio float64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type PurchaseUnitPrice struct {
	Id int64 `xorm:"pk autoincr"`
	Gradient int
	AutoPurchaseRawMaterialSupplierId int64
	StartingQuantity int64
	TerminationQuantity int64
	PurchaseUnitPrice float64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type GiftProportion struct {
	Id int64 `xorm:"pk autoincr"`
	Gradient int
	AutoPurchaseRawMaterialSupplierId int64
	StartingQuantity int64
	TerminationQuantity int64
	Proportion float64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Contract struct {
	Id int64 `xorm:"pk autoincr"`
	Titel string
	SupplierId int64
	SupplierName string
	RawMaterialId int64
	RawMaterialName string
	ExpirationDate time.Time
	CreatedAt time.Time
	UpdatedAt time.Time
}

type AutomaticPurchaseDemand struct {
	Id int64 `xorm:"pk autoincr"`
	DemandStatus int
	FeedbackDemandTime time.Time
	SupplierId int64
	SupplierName string
	OrderAmount float64
	RawMaterialId int64
	RawMaterialName string
	PurchaseQuantity int64
	PurchaseUnitPrice float64
	AutomaticPurchaseDemandPrepaymentList []*AutomaticPurchaseDemandPrepayment `xorm:"-"`
	Give int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type AutomaticPurchaseDemandPrepayment struct {
	Id int64 `xorm:"pk autoincr"`
	AutomaticPurchaseDemandId int64
	Number int
	AutoPurchaseRawMaterialSupplierId int64
	AdvanceRatio float64
	State int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Order struct {
	Id int64 `xorm:"pk autoincr"`
	OrderRawMaterialList []*OrderRawMaterial `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type OrderRawMaterial struct {
	Id int64 `xorm:"pk autoincr"`
	RawMaterialId int64
	RawMaterialName string
	OrderId int64
	Quantity int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type PurchaseOrder struct {
	Id int64 `xorm:"pk autoincr"`
	RawMaterialId int64
	RawMaterialName string
	Quantity int64
	State int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type RelatedRawMaterials struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	RawMaterial []*RawMaterial `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type PrepaidApplicationForm struct {
	Id int64 `xorm:"pk autoincr"`
	RawMaterialId int64
	RawMaterialName string
	Quantity int64
	AmountMoney float64
 	State int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type ExpenseApprovalForm struct {
	Id int64 `xorm:"pk autoincr"`
	RawMaterialId int64
	RawMaterialName string
	Quantity int64
	AmountMoney float64
	State int
	CreatedAt time.Time
	UpdatedAt time.Time
}

func (rm *RawMaterial)GenerateAutomaticPurchaseDemand()([]*AutomaticPurchaseDemand, error){

	w := new(utils.Worker)
	var apdList []*AutomaticPurchaseDemand

	var rwList []*RawMaterial
	x.Where("auto_purchase = ?", 1).Find(&rwList)

	for _, rwv := range rwList{

		var sumSales int64
		var err error
		var daySales int64
		var sumQuanttity int64
		var notOver int64
		var stock int64

		if rwv.Associated == 1{
			sumSales, err = x.Join("INNER", "raw_material", "raw_material.id = order_raw_material.raw_material_id").
				Where("raw_material.related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
				And("order_raw_material.created_at >= ?", time.Now().AddDate(0,0,-15).Format("2006-01-02 15:04:05")).
				SumInt(new(OrderRawMaterial), "quantity")
			if err != nil{
				return nil, err
			}
			fmt.Println("sumSales：", sumSales)

			sumQuanttity, err = x.Join("INNER", "raw_material", "raw_material.id = purchase_order.raw_material_id").
				Where("raw_material.related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
				And("purchase_order.state = ?", 1).
				SumInt(new(PurchaseOrder), "quantity")
			if err != nil{
				return nil, err
			}

			notOver, err = x.Join("INNER", "raw_material", "raw_material.id = automatic_purchase_demand.raw_material_id").
				Where("raw_material.related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
				In("demand_status", []int{1, 2, 4, 6}).
				SumInt(new(AutomaticPurchaseDemand),"purchase_quantity")
			if err != nil{
				return nil, err
			}

			stock, err = x.Where("related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
				SumInt(new(RawMaterial),"stock")
			if err != nil{
				return nil, err
			}

		}else {

			sumSales, err = x.Where("raw_material_id = ?", rwv.Id).And("created_at >= ?", time.Now().AddDate(0, 0, -15).Format("2006-01-02 15:04:05")).SumInt(new(OrderRawMaterial), "quantity")
			if err != nil {
				return nil, err
			}

			sumQuanttity, err = x.Where("raw_material_id = ?", rwv.Id).And("state = ?", 1).SumInt(new(PurchaseOrder), "quantity")
			if err != nil{
				return nil, err
			}

			notOver, err = x.Where("raw_material_id = ?", rwv.Id).In("demand_status", []int{1, 2, 4, 6}).SumInt(new(AutomaticPurchaseDemand),"purchase_quantity")
			if err != nil{
				return nil, err
			}

			stock = rwv.Stock
		}
		daySales = sumSales / 15

		x.Where("raw_material_id = ?", rwv.Id).Asc("purchase_priority").Find(&rwv.AutoPurchaseRawMaterialSupplierList)
		fmt.Println("rwv.AutoPurchaseRawMaterialSupplierList：", rwv.AutoPurchaseRawMaterialSupplierList)

		var purchaseVolume int64
		//defer func(){
		//	err := recover()
		//	if err != nil{
		//		purchaseVolume = 0
		//	}
		//}()

		purchaseVolume = daySales * int64(rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime + 7)

		var initialValue int64 = purchaseVolume

		fmt.Println("rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime：", rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime)
		fmt.Println("purchaseVolume：", purchaseVolume)

		for _, aprsv := range rwv.AutoPurchaseRawMaterialSupplierList{

			if purchaseVolume <= 0{
				break
			}

			var cList []*Contract
			x.SQL("select * from contract where supplier_id = ? and raw_material_id = ? and expiration_date >= ?", aprsv.SupplierId, aprsv.RawMaterialId, time.Now().Format("2006-01-02 15:04:05")).Find(&cList)
			//x.Where("supplier_id = ?", aprsv.SupplierId).And("raw_material_id = ?", aprsv.RawMaterialId).And("expiration_date >= ?", time.Now().Format("2006-01-02 15:04:05")).Find(&cList)
			fmt.Println("cList：", cList)

			fmt.Println("stock + notOver + sumQuanttity：", stock, notOver, sumQuanttity)
			if (stock + notOver + sumQuanttity)/daySales <= int64(rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime + 7) && len(cList) > 0{

				var apd AutomaticPurchaseDemand
				apd.Id = w.GetId()
				apd.DemandStatus = 1
				apd.SupplierId = aprsv.SupplierId
				apd.SupplierName = aprsv.SupplierName
				apd.RawMaterialId = aprsv.RawMaterialId
				apd.RawMaterialName = aprsv.RawMaterialName

				fmt.Println("purchaseVolume：", purchaseVolume)
				fmt.Println("aprsv.MaxQuantification：", aprsv.MaxQuantification)
				if purchaseVolume > aprsv.MaxQuantification{
					apd.PurchaseQuantity = aprsv.MaxQuantification
					purchaseVolume -= aprsv.MaxQuantification
				}else if purchaseVolume >= aprsv.MinQuantification && purchaseVolume <= aprsv.MaxQuantification{
					if purchaseVolume % int64(aprsv.MinNumberPackages) != 0{
						for {
							purchaseVolume += 1
							if purchaseVolume % int64(aprsv.MinNumberPackages) == 0{
								apd.PurchaseQuantity = purchaseVolume
								purchaseVolume = 0
								break
							}
						}
					}else {
						apd.PurchaseQuantity = purchaseVolume
						purchaseVolume = 0
					}
				}else{
					apd.PurchaseQuantity = aprsv.MinQuantification
					purchaseVolume -= aprsv.MinQuantification
				}

				x.Where("auto_purchase_raw_material_supplier_id = ?", aprsv.Id).Asc("gradient").Find(&aprsv.PurchaseUnitPriceList)
				x.Where("auto_purchase_raw_material_supplier_id = ?", aprsv.Id).Asc("number").Find(&aprsv.PrepaymentList)
				for _, pupv := range aprsv.PurchaseUnitPriceList{
					if apd.PurchaseQuantity >= pupv.StartingQuantity &&  apd.PurchaseQuantity <= pupv.TerminationQuantity{

						apd.PurchaseUnitPrice = pupv.PurchaseUnitPrice
						apd.OrderAmount = pupv.PurchaseUnitPrice * float64(apd.PurchaseQuantity) * aprsv.PrepaymentList[0].AdvanceRatio

						break
					}
				}

				if aprsv.AnyGifts == 1 {
					x.Where("auto_purchase_raw_material_supplier_id = ?", aprsv.Id).Asc("gradient").Find(&aprsv.GiftProportionList)
					for _, gpv := range aprsv.GiftProportionList {
						if apd.PurchaseQuantity >= gpv.StartingQuantity && apd.PurchaseQuantity <= gpv.TerminationQuantity {

							apd.Give = aprsv.TemporaryCoordinationGifts + int64(float64(apd.PurchaseQuantity) * gpv.Proportion) + 1

							break
						}
					}
				}

				apd.CreatedAt = time.Now()
				apd.UpdatedAt = time.Now()
				x.Insert(&apd)

				for _, pv := range aprsv.PrepaymentList{
					var p = AutomaticPurchaseDemandPrepayment{
						Id:                                w.GetId(),
						AutomaticPurchaseDemandId:         apd.Id,
						Number:                            pv.Number,
						AutoPurchaseRawMaterialSupplierId: pv.AutoPurchaseRawMaterialSupplierId,
						AdvanceRatio:                      pv.AdvanceRatio,
						State:                             1,
						CreatedAt:                         time.Now(),
						UpdatedAt:                         time.Now(),
					}
					x.Insert(&p)
				}

				apdList = append(apdList, &apd)
			}
		}

		if purchaseVolume > 0 && purchaseVolume < initialValue {
			fmt.Println(rwv.Name+" 剩余：", purchaseVolume, " 未采购")
		}
	}

	return apdList, nil
}

func (rm *RawMaterial)GenerateAutomaticPurchaseDemandAsync()([]*AutomaticPurchaseDemand, error){

	var lock sync.Mutex

	w := new(utils.Worker)
	var apdList []*AutomaticPurchaseDemand

	p := pool.NewSimplePoll(3)
	for i := 0; i < 3; i++ {
		var finalI int = i
		p.Add(func() error {
			var rwList []*RawMaterial
			x.Where("auto_purchase = ?", 1).And("stock = ?", 0).Limit(3, finalI * 3).Find(&rwList)

			for _, rwv := range rwList{

				var sumSales int64
				var err error
				var daySales int64
				var sumQuanttity int64
				var notOver int64
				var stock int64

				if rwv.Associated == 1{
					sumSales, err = x.Join("INNER", "raw_material", "raw_material.id = order_raw_material.raw_material_id").
						Where("raw_material.related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
						And("order_raw_material.created_at >= ?", time.Now().AddDate(0,0,-15).Format("2006-01-02 15:04:05")).
						SumInt(new(OrderRawMaterial), "quantity")
					if err != nil{
						return err
					}
					fmt.Println("sumSales：", sumSales)

					sumQuanttity, err = x.Join("INNER", "raw_material", "raw_material.id = purchase_order.raw_material_id").
						Where("raw_material.related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
						And("purchase_order.state = ?", 1).
						SumInt(new(PurchaseOrder), "quantity")
					if err != nil{
						return err
					}

					notOver, err = x.Join("INNER", "raw_material", "raw_material.id = automatic_purchase_demand.raw_material_id").
						Where("raw_material.related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
						In("demand_status", []int{1, 2, 4, 6}).
						SumInt(new(AutomaticPurchaseDemand),"purchase_quantity")
					if err != nil{
						return err
					}

					stock, err = x.Where("related_raw_materials_id = ?", rwv.RelatedRawMaterialsId).
						SumInt(new(RawMaterial),"stock")
					if err != nil{
						return err
					}

				}else {

					sumSales, err = x.Where("raw_material_id = ?", rwv.Id).And("created_at >= ?", time.Now().AddDate(0, 0, -15).Format("2006-01-02 15:04:05")).SumInt(new(OrderRawMaterial), "quantity")
					if err != nil {
						return err
					}

					sumQuanttity, err = x.Where("raw_material_id = ?", rwv.Id).And("state = ?", 1).SumInt(new(PurchaseOrder), "quantity")
					if err != nil{
						return err
					}

					notOver, err = x.Where("raw_material_id = ?", rwv.Id).In("demand_status", []int{1, 2, 4, 6}).SumInt(new(AutomaticPurchaseDemand),"purchase_quantity")
					if err != nil{
						return err
					}

					stock = rwv.Stock
				}
				daySales = sumSales / 15

				x.Where("raw_material_id = ?", rwv.Id).Asc("purchase_priority").Find(&rwv.AutoPurchaseRawMaterialSupplierList)
				fmt.Println("rwv.AutoPurchaseRawMaterialSupplierList：", rwv.AutoPurchaseRawMaterialSupplierList)

				var purchaseVolume int64
				//defer func(){
				//	err := recover()
				//	if err != nil{
				//		purchaseVolume = 0
				//	}
				//}()

				purchaseVolume = daySales * int64(rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime + 7)

				var initialValue int64 = purchaseVolume

				fmt.Println("rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime：", rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime)
				fmt.Println("purchaseVolume：", purchaseVolume)

				for _, aprsv := range rwv.AutoPurchaseRawMaterialSupplierList{

					if purchaseVolume <= 0{
						break
					}

					var cList []*Contract
					x.SQL("select * from contract where supplier_id = ? and raw_material_id = ? and expiration_date >= ?", aprsv.SupplierId, aprsv.RawMaterialId, time.Now().Format("2006-01-02 15:04:05")).Find(&cList)
					//x.Where("supplier_id = ?", aprsv.SupplierId).And("raw_material_id = ?", aprsv.RawMaterialId).And("expiration_date >= ?", time.Now().Format("2006-01-02 15:04:05")).Find(&cList)
					fmt.Println("cList：", cList)

					fmt.Println("stock + notOver + sumQuanttity：", stock, notOver, sumQuanttity)
					if (stock + notOver + sumQuanttity)/daySales <= int64(rwv.AutoPurchaseRawMaterialSupplierList[0].LeadTime + 7) && len(cList) > 0{

						var apd AutomaticPurchaseDemand
						apd.Id = w.GetId()
						apd.DemandStatus = 1
						apd.SupplierId = aprsv.SupplierId
						apd.SupplierName = aprsv.SupplierName
						apd.RawMaterialId = aprsv.RawMaterialId
						apd.RawMaterialName = aprsv.RawMaterialName

						fmt.Println("purchaseVolume：", purchaseVolume)
						fmt.Println("aprsv.MaxQuantification：", aprsv.MaxQuantification)
						if purchaseVolume > aprsv.MaxQuantification{
							apd.PurchaseQuantity = aprsv.MaxQuantification
							purchaseVolume -= aprsv.MaxQuantification
						}else if purchaseVolume >= aprsv.MinQuantification && purchaseVolume <= aprsv.MaxQuantification{
							if purchaseVolume % int64(aprsv.MinNumberPackages) != 0{
								for {
									purchaseVolume += 1
									if purchaseVolume % int64(aprsv.MinNumberPackages) == 0{
										apd.PurchaseQuantity = purchaseVolume
										purchaseVolume = 0
										break
									}
								}
							}else {
								apd.PurchaseQuantity = purchaseVolume
								purchaseVolume = 0
							}
						}else{
							apd.PurchaseQuantity = aprsv.MinQuantification
							purchaseVolume -= aprsv.MinQuantification
						}

						x.Where("auto_purchase_raw_material_supplier_id = ?", aprsv.Id).Asc("gradient").Find(&aprsv.PurchaseUnitPriceList)
						x.Where("auto_purchase_raw_material_supplier_id = ?", aprsv.Id).Asc("number").Find(&aprsv.PrepaymentList)
						for _, pupv := range aprsv.PurchaseUnitPriceList{
							if apd.PurchaseQuantity >= pupv.StartingQuantity &&  apd.PurchaseQuantity <= pupv.TerminationQuantity{

								apd.PurchaseUnitPrice = pupv.PurchaseUnitPrice
								apd.OrderAmount = pupv.PurchaseUnitPrice * float64(apd.PurchaseQuantity) * aprsv.PrepaymentList[0].AdvanceRatio

								break
							}
						}

						if aprsv.AnyGifts == 1 {
							x.Where("auto_purchase_raw_material_supplier_id = ?", aprsv.Id).Asc("gradient").Find(&aprsv.GiftProportionList)
							for _, gpv := range aprsv.GiftProportionList {
								if apd.PurchaseQuantity >= gpv.StartingQuantity && apd.PurchaseQuantity <= gpv.TerminationQuantity {

									apd.Give = aprsv.TemporaryCoordinationGifts + int64(float64(apd.PurchaseQuantity) * gpv.Proportion) + 1

									break
								}
							}
						}

						apd.CreatedAt = time.Now()
						apd.UpdatedAt = time.Now()
						x.Insert(&apd)

						for _, pv := range aprsv.PrepaymentList{
							var p = AutomaticPurchaseDemandPrepayment{
								Id:                                w.GetId(),
								AutomaticPurchaseDemandId:         apd.Id,
								Number:                            pv.Number,
								AutoPurchaseRawMaterialSupplierId: pv.AutoPurchaseRawMaterialSupplierId,
								AdvanceRatio:                      pv.AdvanceRatio,
								State:                             1,
								CreatedAt:                         time.Now(),
								UpdatedAt:                         time.Now(),
							}
							x.Insert(&p)
						}

						lock.Lock()

						apdList = append(apdList, &apd)

						lock.Unlock()
					}
				}

				if purchaseVolume > 0 && purchaseVolume < initialValue {
					fmt.Println(rwv.Name+" 剩余：", purchaseVolume, " 未采购")
				}
			}

			return nil
		})
	}
	p.Run()

	return apdList, nil
}

func (rm *RawMaterial)InsertAutoPurchaseRawMaterialSupplier(aprsList string, rawMaterialId int64, rawMaterialName string)(map[string]interface{}, error){

	w := new(utils.Worker)

	var a = Audit{
		Id:                            w.GetId(),
		RawMaterialId:                 rawMaterialId,
		RawMaterialName:               rawMaterialName,
		AutommaticPurchaseInformation: aprsList,
		State:                         1,
		CreatedAt:                     time.Now(),
		UpdatedAt:                     time.Now(),
	}

	fmt.Println("a：", a)

	x.Insert(&a)

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (rm *RawMaterial)QueryRawMaterialInfo(rwId int64) (*RawMaterial, error){

	rawMaterial := new(RawMaterial)
	x.Id(rwId).Get(rawMaterial)

	//if rawMaterial.AutomaticPurchaseAuditStatus == 2{
	x.Where("raw_material_id = ?", rawMaterial.Id).Asc("purchase_priority").Find(&rawMaterial.AutoPurchaseRawMaterialSupplierList)
	for _, aprs := range rawMaterial.AutoPurchaseRawMaterialSupplierList{
		x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Asc("gradient").Find(&aprs.PurchaseUnitPriceList)
		x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Asc("number").Find(&aprs.PrepaymentList)
		x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Asc("gradient").Find(&aprs.GiftProportionList)
	}
	//}

	return rawMaterial, nil
}

type Audit struct {
	Id int64 `xorm:"pk autoincr"`
	RawMaterialId int64
	RawMaterialName string
	AutommaticPurchaseInformation string `xorm:"varchar(20480)"`
	AutoPurchaseRawMaterialSupplierList []*AutoPurchaseRawMaterialSupplier `xorm:"-"`
	State int
	CreatedAt time.Time
	UpdatedAt time.Time
}

func (rm *RawMaterial)AutommaticPurchaseInformationAudit(auditId int64, result string)(map[string]interface{}, error){

	var a Audit
	x.Id(auditId).Get(&a)

	if result == "1" {

		w := new(utils.Worker)

		rawMaterial := new(RawMaterial)
		x.Id(a.RawMaterialId).Get(rawMaterial)

		x.Where("raw_material_id = ?", rawMaterial.Id).Find(&rawMaterial.AutoPurchaseRawMaterialSupplierList)
		for _, aprs := range rawMaterial.AutoPurchaseRawMaterialSupplierList{

			x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Delete(new(PurchaseUnitPrice))

			x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Delete(new(Prepayment))

			x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Delete(new(GiftProportion))
		}
		x.Where("raw_material_id = ?", rawMaterial.Id).Delete(new(AutoPurchaseRawMaterialSupplier))

		var aprsList []*AutoPurchaseRawMaterialSupplier
		jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(a.AutommaticPurchaseInformation), &aprsList)
		for _, aprs := range aprsList {
			aprs.Id = w.GetId()
			aprs.CreatedAt = time.Now()
			aprs.UpdatedAt = time.Now()
			x.Insert(aprs)

			for _, pv := range aprs.PrepaymentList {
				pv.Id = w.GetId()
				pv.AutoPurchaseRawMaterialSupplierId = aprs.Id
				pv.CreatedAt = time.Now()
				pv.UpdatedAt = time.Now()
				x.Insert(pv)
			}

			for _, pupv := range aprs.PurchaseUnitPriceList {
				pupv.Id = w.GetId()
				pupv.AutoPurchaseRawMaterialSupplierId = aprs.Id
				pupv.CreatedAt = time.Now()
				pupv.UpdatedAt = time.Now()
				x.Insert(pupv)
			}

			for _, gpv := range aprs.GiftProportionList {
				gpv.AutoPurchaseRawMaterialSupplierId = aprs.Id
				gpv.Id = w.GetId()
				gpv.CreatedAt = time.Now()
				gpv.UpdatedAt = time.Now()
				x.Insert(gpv)
			}
		}

		a.State = 2
		x.Id(a.Id).Update(&a)
	}else {

		a.State = 3
		x.Id(a.Id).Update(&a)
	}

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (rm *RawMaterial)AutommaticPurchaseInformationAuditAsync(auditId int64, result string)(map[string]interface{}, error){

	var a Audit
	x.Id(auditId).Get(&a)

	if result == "1" {

		w := new(utils.Worker)

		rawMaterial := new(RawMaterial)
		x.Id(a.RawMaterialId).Get(rawMaterial)

		x.Where("raw_material_id = ?", rawMaterial.Id).Find(&rawMaterial.AutoPurchaseRawMaterialSupplierList)
		for _, aprs := range rawMaterial.AutoPurchaseRawMaterialSupplierList{

			x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Delete(new(PurchaseUnitPrice))

			x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Delete(new(Prepayment))

			x.Where("auto_purchase_raw_material_supplier_id = ?", aprs.Id).Delete(new(GiftProportion))
		}
		x.Where("raw_material_id = ?", rawMaterial.Id).Delete(new(AutoPurchaseRawMaterialSupplier))

		var wg sync.WaitGroup
		wg.Add(3)

		var aprsList []*AutoPurchaseRawMaterialSupplier
		jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(a.AutommaticPurchaseInformation), &aprsList)

		for i := 0; i < 3; i++ {
			var actual int = i
			go func() {
				defer func() {
					// 捕获异常 防止waitGroup阻塞
					if err := recover(); err != nil {
						wg.Done()
					}
				}()

				aprs := aprsList[actual]
				aprs.Id = w.GetId()
				aprs.CreatedAt = time.Now()
				aprs.UpdatedAt = time.Now()
				x.Insert(aprs)

				for _, pv := range aprs.PrepaymentList {
					pv.Id = w.GetId()
					pv.AutoPurchaseRawMaterialSupplierId = aprs.Id
					pv.CreatedAt = time.Now()
					pv.UpdatedAt = time.Now()
					x.Insert(pv)
				}

				for _, pupv := range aprs.PurchaseUnitPriceList {
					pupv.Id = w.GetId()
					pupv.AutoPurchaseRawMaterialSupplierId = aprs.Id
					pupv.CreatedAt = time.Now()
					pupv.UpdatedAt = time.Now()
					x.Insert(pupv)
				}

				for _, gpv := range aprs.GiftProportionList {
					gpv.AutoPurchaseRawMaterialSupplierId = aprs.Id
					gpv.Id = w.GetId()
					gpv.CreatedAt = time.Now()
					gpv.UpdatedAt = time.Now()
					x.Insert(gpv)
				}

				wg.Done()
			}()
		}

		wg.Wait()

		a.State = 2
		x.Id(a.Id).Update(&a)
	}else {

		a.State = 3
		x.Id(a.Id).Update(&a)
	}

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (rm *RawMaterial)QueryAuditDetails(rawMaterialId int64)([]*Audit, error){

	var aList []*Audit
	//x.SQL("select * from audit where raw_material_id = ? order by created_at desc limit 2 ", rawMaterialId).Find(&aList)
	x.Where("raw_material_id = ?", rawMaterialId).Limit(2).Desc("created_at").Find(&aList)

	for _, a := range aList{
		jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(a.AutommaticPurchaseInformation), &a.AutoPurchaseRawMaterialSupplierList)
	}

	return aList, nil
}

func (rm *RawMaterial)GeneratePurchaseOrder(apdId int64)(map[string]interface{}, error){

	w := new(utils.Worker)

	var apd AutomaticPurchaseDemand
	x.Id(apdId).Get(&apd)

	var po = PurchaseOrder{
		Id:              w.GetId(),
		RawMaterialId:   apd.RawMaterialId,
		RawMaterialName: apd.RawMaterialName,
		Quantity:        apd.PurchaseQuantity,
		State:           1,
		CreatedAt:       time.Now(),
		UpdatedAt:       time.Now(),
	}
	x.Insert(&po)

	apd.DemandStatus = 4
	x.Id(apd.Id).Update(&apd)

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (rm *RawMaterial)GenerateAdvancePaymentDocument(poId int64)(map[string]interface{}, error){

	w := new(utils.Worker)

	var po PurchaseOrder
	x.Id(poId).Get(&po)

	var paf = PrepaidApplicationForm{
		Id:              w.GetId(),
		RawMaterialId:   po.RawMaterialId,
		RawMaterialName: po.RawMaterialName,
		Quantity:        po.Quantity,
		AmountMoney:     float64(po.Quantity)*1.6,   //数量*单价
		State:           1,
		CreatedAt:       time.Now(),
		UpdatedAt:       time.Now(),
	}
	x.Insert(&paf)

	po.State = 2
	x.Id(po.Id).Update(&po)

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (rm *RawMaterial)GenerateExpenseApprovalDocument(pafId int64)(map[string]interface{}, error){

	w := new(utils.Worker)

	var paf PrepaidApplicationForm
	x.Id(pafId).Get(&paf)

	var eaf = ExpenseApprovalForm{
		Id:              w.GetId(),
		RawMaterialId:   paf.RawMaterialId,
		RawMaterialName: paf.RawMaterialName,
		Quantity:        paf.Quantity,
		AmountMoney:     float64(paf.Quantity)*1.6,   //数量*单价
		State:           1,
		CreatedAt:       time.Now(),
		UpdatedAt:       time.Now(),
	}
	x.Insert(&eaf)

	paf.State = 2
	x.Id(paf.Id).Update(&paf)

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}






















































